import { defineComponent, nextTick, onMounted, ref } from 'vue';
import { BasicModal, useModalInner } from '@/components/Modal';
import { useMessage } from '@/hooks/web/useMessage';
import { useUserStore } from '/@/store/modules/user';
import { leaveReserveSeatApi, seatReserveSeatApi } from '../service';

export default defineComponent({
  name: 'SeatedModal',
  emits: ['register', 'reload'],
  setup(_, { emit }) {
    const {
      createMessage: { success, error: errorMessage },
    } = useMessage();
    const userStore = useUserStore();

    let takePhoto = () => {};
    const faceUrl = ref('');
    let types = 'add';
    let ReserveSeatID = '';
    const [registerModal, { changeLoading, changeOkLoading, closeModal, setModalProps }] =
      useModalInner(async ({ record, type = 'add' }) => {
        changeLoading(true);
        changeOkLoading(true);
        types = type;
        ReserveSeatID = record.ReserveSeatID;
        setModalProps({ title: `${type === 'add' ? '入座' : '编辑'}认证` });
        faceUrl.value = '';
        const video: any = document.querySelector('#video');
        const canvas: any = document.querySelector('#canvas');
        const ctx: any = canvas.getContext('2d');
        const errorDiv: any = document.querySelector('#error');

        canvas.width = canvas.height = 400;

        try {
          const stream = await navigator.mediaDevices.getUserMedia({
            video: { width: 400, height: 400 },
          });
          video.srcObject = stream;
          video.onloadedmetadata = () => video.play();
        } catch (err) {
          console.error('摄像头访问失败:', err);
          errorDiv.textContent = '无法访问摄像头，请检查设备或权限设置。';
        }

        takePhoto = function capturePhoto() {
          if (!video.srcObject) {
            errorDiv.textContent = '没有检测到摄像头，无法拍照。';
            return;
          }

          ctx.drawImage(video, 0, 0, 400, 400);
          faceUrl.value = canvas.toDataURL('image/png');
          nextTick(() => {
            (document.getElementById('imgXX') as any).src = faceUrl.value;
          });
        };

        changeLoading(false);
        changeOkLoading(false);
      });

    // 加载人脸识别模型
    async function loadModels() {
      try {
        // @ts-ignore
        await faceapi.nets.ssdMobilenetv1.loadFromUri('../face-model');
        // @ts-ignore
        await faceapi.nets.faceLandmark68Net.loadFromUri('../face-model');
        // @ts-ignore
        await faceapi.nets.faceRecognitionNet.loadFromUri('../face-model');
      } catch (e) {
        console.error('加载人脸模型失败:', e);
        throw new Error('加载人脸识别模型失败');
      }
    }

    // 获取人脸特征（添加跨域处理）
    async function getFaceDescriptor(imageUrl: string, isCrossOrigin = true) {
      return new Promise<any>(async (resolve) => {
        const img = new Image();
        if (isCrossOrigin) {
          img.crossOrigin = 'Anonymous'; // 解决跨域问题
        }
        img.src = imageUrl;

        img.onload = async () => {
          try {
            // @ts-ignore
            const detection = await faceapi
              .detectSingleFace(img)
              .withFaceLandmarks()
              .withFaceDescriptor();
            resolve(detection ? detection.descriptor : null);
          } catch (e) {
            console.error('人脸检测失败:', e);
            resolve(null);
          }
        };

        img.onerror = () => {
          console.error('图片加载失败:', imageUrl);
          resolve(null);
        };
      });
    }

    // 计算相似度
    function cosineSimilarity(a: any, b: any) {
      let dot = 0,
        normA = 0,
        normB = 0;
      for (let i = 0; i < a.length; i++) {
        dot += a[i] * b[i];
        normA += a[i] ** 2;
        normB += b[i] ** 2;
      }
      return dot / (Math.sqrt(normA) * Math.sqrt(normB));
    }

    const handleSubmit = async () => {
      changeLoading(true);
      changeOkLoading(true);

      try {
        // 1. 拍照
        takePhoto();
        // if (!faceUrl.value) {
        //   throw new Error('请先拍照');
        // }

        // 2. 加载模型
        await loadModels();

        // 3. 获取预设图片（用户头像）
        const avatarUrl = (userStore.getUserInfo as any)?.FaceUrl;

        // 4. 获取人脸特征（处理可能跨域的头像）
        const presetDescriptor = await getFaceDescriptor(avatarUrl, true);
        if (!presetDescriptor) {
          throw new Error('预设图片中未检测到人脸或图片加载失败');
        }

        // 5. 获取拍照图片特征（本地图片不需要跨域处理）
        const capturedImg = document.getElementById('imgXX') as HTMLImageElement;
        const capturedDescriptor = await getFaceDescriptor(capturedImg.src, false);
        if (!capturedDescriptor) {
          throw new Error('拍摄照片中未检测到人脸');
        }
        // 6. 计算相似度
        const similarity = cosineSimilarity(presetDescriptor, capturedDescriptor);
        console.log('人脸相似度:', similarity);

        // 7. 判断结果（阈值设为0.8）
        if (similarity >= 0.95) {
          success('人脸匹配成功');
          if (types === 'add') {
            // 入座
            await seatReserveSeatApi({
              ReserveSeatID,
            });
          } else {
            // 离座
            await leaveReserveSeatApi({
              ReserveSeatID,
            });
          }
          closeModal();
          emit('reload');
        } else {
          errorMessage('人脸不匹配，请重新尝试');
        }
      } catch (err: any) {
        errorMessage(err.message || '人脸比对失败');
      } finally {
        faceUrl.value = '';
        changeLoading(false);
        changeOkLoading(false);
      }
    };

    return () => (
      <BasicModal
        width={400}
        minHeight={400}
        onRegister={registerModal}
        destroyOnClose
        onOk={handleSubmit}
      >
        <div>
          <div class={faceUrl.value ? 'hidden' : ''}>
            <video id="video" autoplay width="400" height="400"></video>
            <canvas id="canvas" style="display: none;"></canvas>
          </div>
          <div class={faceUrl.value ? '' : 'hidden'}>
            <img id="imgXX" src="" width="400" height="400" />
          </div>
        </div>
        <div id="error" style="color: red; margin-top: 10px;"></div>
      </BasicModal>
    );
  },
});
